using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace LevelData
{
    //this is the type of collision
    public enum TileCollision
    {
        Passable = 0,
        Impassable = 1,
        Platform = 2,
    }

    //this is the type of object
    public enum ObjectType
    {
        Money = 10,
        PoisonHealt = 1,
        PoisonHealtPlus = 2,
        Gold = 50,
        Star = 5,
        DoorA = 98,
        OpenDoorA = 99,
        DoorB = 97,
        OpenDoorB = 96,
        DoorC = 95,
        OpenDoorC = 94,
        Exit = 93,
        openExit = 92,
        CheckPoint = 91
    }

    //this is the type of enemy
    public enum EnemyType
    {
        Monster = 150,
        Thorns = 0,
        Guillottine = 300,
    }

    //this is the color of enemy
    public enum ColorEnemy
    {
        Yellow = 0,
        Red,
        Green,
        noColor
    }

    public enum SoundType
    { 
        jump = 0,
        battlePlayer = 1,
        battleEnemy = 17,
        diePlayer = 2,
        dieEnemy = 16,
        star = 4,
        openDoor = 5,
        door = 11,
        nextLevel = 6,
        poison = 7,
        dollar = 8,
        invulnerability = 9,
        noSound = 10,
        musicPlay = 15,
        musicStop = 12,
        storyPlay = 13,
        storyStop = 14
    }

    //this is a player direction when run
    public enum FaceDirection
    {
        Left = -1,
        Right = 1,
    }

    //this is a structure of a tile
    public class Tile
    {
        public TileCollision Collision;
#if WINDOWS_PHONE
        public const int Width = 50;
        public const int Height = 40;
#else
        public const int Width = 50;
        public const int Height = 40;
#endif
        public static readonly Vector2 Size = new Vector2(Width, Height);

        public Tile() { }
        public Tile(TileCollision collision)
        {
            Collision = collision;
        }
    }

    public class ObjGame
    {
        public ObjectType type;
        public AnimationPlayer sprite;
        public int typeDoor;
        public bool take = false;
        public int posX;
        public int posY;        

        public bool open = false;

        public Vector2 position;

        public ObjGame() { }
        public ObjGame(int x, int y, ObjectType type)
        {
            position = new Vector2(x * Tile.Size.X, y * Tile.Size.Y);
            this.type = type;
            posX = x;
            posY = y;
        }

        public Rectangle BoundingRectangle
        {
            get
            {
                return new Rectangle((int)position.X, (int)position.Y, Tile.Width, Tile.Height);
            }
        }
    }

    public class Enemy
    { 
        public int left;
        public int top;
        public Vector2 position;
        public Vector2 start;
        public FaceDirection direction = FaceDirection.Left;
        public float waitTime = 0.0f;
        public float MaxWaitTime = 0.5f;
        public float MoveSpeed;
        public EnemyType type;
        public AnimationPlayer sprite;
        public bool die = false;
        public bool isDieing = false;
        public float timeAttack;
        public float timeAttackToAttack = 1;
        public bool onFighting = true;
        public bool hit = false;

        public int posX;
        public int posY;

        public int health;
        public ColorEnemy color;

        public Rectangle localBounds;

        public Enemy() { }
        public Enemy(int x, int y, EnemyType type, ColorEnemy color)
        {
            start = new Vector2(x * Tile.Size.X, y * Tile.Size.Y);
            position = start;
            posX = x;
            posY = y;
            this.type = type;
            this.color = color;
            MoveSpeed = (int)type;
        }

        public Rectangle BoundingRectangle
        {
            get
            {
                left = (int)Math.Round(position.X) + localBounds.X;
                top = (int)Math.Round(position.Y) + localBounds.Y;
                return new Rectangle(left, top, localBounds.Width, localBounds.Height);
            }
        }
    }

    public struct block
    {
        public int width;
        public int height;

        public int posX;
        public int posY;
        public int type;

        public block(int x, int y, int type)
        {
            posX = x;
            posY = y;
            this.type = type;
            width = Tile.Width;
            height = Tile.Height;
        }
    }

    public class player
    {
        public int left;
        public int top;
        public Vector2 position;
        public Vector2 start;
        public float movement;
        public bool isJumping;
        public bool isRunning;
        public bool wasJumping;
        public float jumpTime;
        public bool isOnGround;
        public bool isAlive;
        public Vector2 velocity;
        public float previousBottom;
        public bool onExit;
        public int points = 0;
        public int life = 3;
        public bool exit = false;
        public float invulnerability = 0;
        public float timeInvulnerability = 0;
        public bool stopSound = false;
        public bool orientationSx = false;
        
        public bool hit = false;
        public bool hitByEnemy = false;

        public int health;

        public float timeAttack = 0;
        public float timeAttackToAttack = 1;
        public bool onFighting;

        public AnimationPlayer sprite;
        public float dieTime = 0;
        public TimeSpan timeRemaining = TimeSpan.FromMinutes(2.0);

        public Rectangle localBounds;

        public player() { }
        public player(int x, int y)
        {
            position = new Vector2(x * Tile.Size.X, (y-1) * Tile.Size.Y);
            start = position;
            movement = 0.0f;
            isJumping = false;
            isRunning = false;
            wasJumping = false;
            jumpTime = 0.0f;
            isOnGround = false;
            isAlive = true;
            velocity = Vector2.Zero;
            previousBottom = 0;// position.Y + height;
            onExit = false;
            onFighting = true;
            health = 3;

            //this is a bounding rect of the player
            localBounds = new Rectangle(18, 0, (int)(45), (int)(80));
        }

        public Rectangle BoundingRectangle
        {
            get
            {
                //if(orientationSx == true)
                    left = (int)Math.Round(position.X) + localBounds.X;
                //else
                  //  left = (int)Math.Round(position.X);
                top = (int)Math.Round(position.Y) + localBounds.Y;
                return new Rectangle(left, top, localBounds.Width, localBounds.Height);
            }
        }
    }

    public struct platform
    {
        public int width;
        public int height;
        public int posX;
        public int posY;

        public platform(int x, int y)
        {
            posX = x;
            posY = y;
            width = 50;
            height = 40;
        }
    }
    
    public class Level
    {
        public List<ObjGame> ObjectList = new List<ObjGame>();
        public List<Enemy> enemyList = new List<Enemy>();
        public List<block> blockList = new List<block>();
        public List<platform> platformList = new List<platform>();
        public player playerLevel = new player();
        public List<Tile> tiles = new List<Tile>();
        public List<SoundType> soundList = new List<SoundType>();
        public int lenghtX = 0;
        public int lenghtY = 0;
        public int numLevel = 0;
        public double totalGameTime = 0;
        public float menuDieTime = 0.0f;
        public bool storyMode = false;

        public Level()
        {
        }

        //return the collision type of a tile
        public TileCollision GetCollision(int x, int y)
        {
            int position = x + y * lenghtX;
            if (position < tiles.Count && position >= 0)
            {
                return tiles[position].Collision;
            }
            else
            {
                return TileCollision.Passable;
            }
        }

        public void SetCollision(int x, int y)
        {
            int position = x + y * lenghtX;

            tiles[position].Collision = TileCollision.Passable;
            
        }

        //get the bound of a tile
        public Rectangle GetBounds(int x, int y)
        {
            for (int i = 0; i < ObjectList.Count(); i++)
                if (ObjectList[i].posX == x && ObjectList[i].posY == y)
                    return ObjectList[i].BoundingRectangle;

            return new Rectangle(x * Tile.Width, y * Tile.Height, Tile.Width, Tile.Height);
        }

        public Vector2 checkVisibleHArea(float cameraPosition)
        {
            Vector2 visibleHArea = new Vector2();
            
            visibleHArea.X = (int)Math.Floor(cameraPosition / Tile.Width);
            visibleHArea.Y = visibleHArea.X + GraphicsDeviceManager.DefaultBackBufferWidth / Tile.Width;
            visibleHArea.Y = Math.Min(visibleHArea.Y, lenghtX);

            return visibleHArea;
        }

        public Vector2 checkVisibleVArea(float cameraPosition)
        {
            Vector2 visibleArea = new Vector2();
            
            visibleArea.X = (int)Math.Floor(cameraPosition / Tile.Height);
            visibleArea.Y = visibleArea.X + GraphicsDeviceManager.DefaultBackBufferHeight / Tile.Height;
            visibleArea.Y = Math.Min(visibleArea.Y, lenghtY);

            return visibleArea;
        }

    }
}

